import React,{useState, useEffect, useMemo, useCallback,useLayoutEffect, useReducer, useContext} from 'react'
const MyContext = React.createContext();


function reducer(state={num3: 0}, action) {
  switch (action.type) {
    case 'ADD':
      return {num3: state.num3+1}
    case 'MINUS':
      return {num3: state.num3-1}
    default:
      break;
  }
}


// useLayoutEffect
function Animation(props) {
  const ref = React.useRef()
  let style = {
    width: '100px',
    height: '100px',
    backgroundColor: 'red'
  }
  // 在渲染之后
  // useEffect(()=>{
  //   ref.current.style.transform = `translate(500px)`
  //   ref.current.style.transition = `all 500ms`
  // }, [])
  // 在渲染之前
  useLayoutEffect(()=>{
    ref.current.style.transform = `translate(500px)`
    ref.current.style.transition = `all 500ms`
  }, [])
  return (
    <div style={style} ref={ref}></div>
  )
}


// forwardRef  + useImperativeHandle
// function RefChild(props, forwardRef) {
//   console.log(forwardRef)
//   return (
//     <div>
//       <input type="text" ref={forwardRef} />
//     </div>
//   )
// } 
function RefChild(props, forwardRef) {
  // console.log(forwardRef)
  const inputRef = React.useRef()
  React.useImperativeHandle(forwardRef, ()=>({
    focus() {
      inputRef.current.focus()
    }
  }))
  return (
    <div>
      <input type="text" ref={inputRef} />
    </div>
  )
} 
const ForwardChild = React.forwardRef(RefChild)
function ForwardTest() {
  let inputRef = React.useRef()
  let getFocus = () => {
    inputRef.current.focus()
  }
  return (
    <div>
      <ForwardChild ref={inputRef}></ForwardChild>
      <button onClick={getFocus}>add</button>
    </div>
  )
}


// PureComponent优化  props state  
class Test extends React.PureComponent{
  constructor(props) {
    super(props)
    this.state = {
      num: 0
    }
  }
  add = () => {
    this.setState({
      num: 0
    })
  }
  render(){
    console.log('render')
    return <div onClick={this.add}>{this.state.num}</div>
  }
}


// useCallback  缓存函数的
function Child({data, handleClick}) {
  console.log('child render')
  return (
    <button onClick={handleClick}>{data.number}</button>
  )
}
const MemoChild = React.memo(Child)
// useMemo  类似于计算属性


// 
function ContextChild() {
  const {state, dispatch} = useContext(MyContext)
  const [num, setNum] = useState(1)
  return (
    <div>
      {num}
      {state.num3}
      <button onClick={()=>dispatch({type: 'ADD'})}>++</button>
      <button onClick={()=>setNum(num+1)}>++</button>
    </div>
  )
}


function HooksTest() {
  const [num, setNum] = useState(1)
  const [num2, setNum2] = useState(1)
  const [state, dispatch] = useReducer(reducer, {num3: 0})
  
  

  useEffect(()=>{
    console.log('??')
  }, [num, num2])

  useEffect(()=>{
    const timer = setInterval(()=>{
      // console.log(1)
    }, 1000)
    // 返回一个函数回调   销毁
    return () => {
      clearInterval(timer)
    }
    // 依赖项
  }, [])

  const add = () => {
    // setNum(num+1)
    // setNum(x => x+1)
    setNum2(num2+1)
  }

  // 每次更新这个两个 都会内存地址都会变化  导致MemoChild 每次也会更新
  // 所以对数据  跟  handleClick做个缓存
  // let data = {
  //   number: num
  // }
  const data = useMemo(()=>{
    return {number: num}
  }, [num])

  // const handleClick = () => {
  //   setNum(num+1)
  // }
  const handleClick = useCallback(()=>{
    setNum(num+1)
  }, [num])
  console.log('render')

  // useLayoutEffect  同步 更新dom 绘制之前执行

  // useImperativeHandle




  return (
    <MyContext.Provider value={{ state, dispatch }}>
      <>
        <div>{state.num3}</div>
        <button onClick={()=>dispatch({type: 'ADD'})}>+</button>
        <button onClick={()=>dispatch({type: 'MINUS'})}>-</button>
        <button>+</button>
        <Test></Test>
        <MemoChild data={data} handleClick={handleClick}></MemoChild>
        <div onClick={add}>{num}{num2}</div>
        <Animation/>
        <ForwardTest/>
        <ContextChild></ContextChild>
      </>
    </MyContext.Provider>

  )
}

export default HooksTest